package IL;

import static org.objectweb.asm.Opcodes.GOTO;
import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.IFGE;
import static org.objectweb.asm.Opcodes.IFGT;
import static org.objectweb.asm.Opcodes.IFLE;
import static org.objectweb.asm.Opcodes.IFLT;
import static org.objectweb.asm.Opcodes.IFNE;
import static org.objectweb.asm.Opcodes.IF_ACMPEQ;
import static org.objectweb.asm.Opcodes.IF_ACMPNE;
import static org.objectweb.asm.Opcodes.IF_ICMPEQ;
import static org.objectweb.asm.Opcodes.IF_ICMPGE;
import static org.objectweb.asm.Opcodes.IF_ICMPGT;
import static org.objectweb.asm.Opcodes.IF_ICMPLE;
import static org.objectweb.asm.Opcodes.IF_ICMPLT;
import static org.objectweb.asm.Opcodes.IF_ICMPNE;
import static org.objectweb.asm.Opcodes.JSR;
import static org.objectweb.asm.Opcodes.NEW;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static org.objectweb.asm.Opcodes.*;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.Type;

import ILTypes.ILMethod;

public class MethodGenerator {

	ILMethod meth;
	int instructionCount;
	int multiArrayFlag;
	String multiArraySignature;
	List<String> tempInstructions;
	List<String> ls;
	List<String> pendingTypeLists;

	public List<String> methInstructions;

	public MethodGenerator()
	{
		meth = new ILMethod();
		ls = new ArrayList<String>();
		tempInstructions = new ArrayList<String>();
		methInstructions = new ArrayList<String>();
		pendingTypeLists = new ArrayList<String>();
		multiArraySignature = "";
		instructionCount = 0;
		multiArrayFlag = 0;
	}
	
	public MethodGenerator(ILMethod iMl)
	{
		this.meth = iMl;
		ls = new ArrayList<String>();
		tempInstructions = new ArrayList<String>();
		methInstructions = new ArrayList<String>();
		pendingTypeLists = new ArrayList<String>();
		
		multiArraySignature = "";
		instructionCount = 0;
		multiArrayFlag = 0;
	}

	
	public void visitMethod()
	{
		StringBuffer methDecl = new StringBuffer();
		String methodName = meth.GetName();
		String desc = meth.GetDescription();
		Type retTye = Type.getReturnType(desc);
		
		instructionCount = 0;
		
		//System.out.println("## :"+access+ " "+methodName+" "+desc+" ");

	    //	   staticMethod = true; 
		
		if(methodName.equalsIgnoreCase("main"))
		{
			tempInstructions.add(".method static void main() cil managed {\n");
			tempInstructions.add("\n");
			tempInstructions.add("   .entrypoint\n\n");
		}
		else
		{
			if(methodName.contains("<init>")) {
				
				methDecl.append(".method public hidebysig specialname rtspecialname instance void  .ctor");
				methDecl.append(ILUtility.getFormattedIlParams(meth.GetParameters()));
				methDecl.append(" cil managed {\n\n");
				tempInstructions.add(methDecl.toString());
			}
			
			else {
				
				methDecl.append(".method public hidebysig instance " + ILUtility.resolveShortType(retTye.toString()) + " ");
				methDecl.append(meth.GetName());
				methDecl.append(ILUtility.getFormattedIlParams(meth.GetParameters()));
				methDecl.append(" cil managed {\n\n");
				tempInstructions.add(methDecl.toString());
				
			}
		}
	}
	
	public void dealLoadStoreInstructions(int opcode, int var)
	{
		
		int argCount = meth.GetParametersCount();
		int target;
		String instruction="";
		
		
		
		if(opcode == ILOAD || opcode == LLOAD||opcode == DLOAD|| opcode == FLOAD || opcode == ALOAD)
		{
			if(meth.isStatic)
				argCount--;
				
			if(var<=argCount){
					instruction = "ldarg";
					target = var;
			}		
			else{
				
				target = (var-argCount-1);
				
				instruction = "ldloc";
			}		
			
			if(target<=3)
				tempInstructions.add("   "+instruction+"."+target+"\n");
			else
				tempInstructions.add("   "+instruction+" "+target+"\n");
				
		}	
		
		if(opcode == ISTORE || opcode == LSTORE||opcode == DSTORE|| opcode == FSTORE || opcode == ASTORE)
		{
			if(meth.isStatic)
				argCount--;
				
			if(var<=argCount){
					instruction = "starg";
					target = var;
			}		
			else{
				
				target = (var-argCount-1);
				instruction = "stloc";
			}	
			
			if(target<=3)
				tempInstructions.add("   "+instruction+"."+target+"\n");
			else
				tempInstructions.add("   "+instruction+" "+target+"\n");
		}	
	}
	
	// Instruction with Single operand
	public void toCorrespondingIL(String instruction, String operand) throws IOException
	{
		/***    RET  *****/
		
		if(instruction.equalsIgnoreCase("RET")){
			tempInstructions.add("   "+"ret"+"\n"); // Not sure 
			instructionCount++;
		}	
		
		/*if(instruction.equalsIgnoreCase("ILOAD")||instruction.equalsIgnoreCase("LLOAD")||instruction.equalsIgnoreCase("DLOAD")||instruction.equalsIgnoreCase("FLOAD")||instruction.equalsIgnoreCase("ALOAD")){
			
				//System.out.println("@@@@:"+Integer.parseInt(operand));
				tempInstructions.add("   "+"ldloc "+operand+"\n");
				instructionCount++;
		}*/
		
		/*
		 * *
		 * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
		 * 
		 */
		
		/*if(instruction.equalsIgnoreCase("ISTORE")||instruction.equalsIgnoreCase("LSTORE")||instruction.equalsIgnoreCase("DSTORE")||instruction.equalsIgnoreCase("FSTORE")||instruction.equalsIgnoreCase("ASTORE")){
			tempInstructions.add("   "+"stloc "+operand+"\n");
			instructionCount++;
		}*/
		
		/*
		 * *
		 ** LDC, LDC_w and LDC2_w
		 * 
		 */
		
		if(instruction.startsWith("ldc"))
		{
			tempInstructions.add("   "+"ldstr "+"\""+ operand+"\""+"\n");
			instructionCount++;
		}
	}

	

	/***************************************************/
	
	// Instruction with Single operand (Integer)       ///
	/****************************************************/	
	
	
	public void toCorrespondingIL(String instruction,int operand) throws IOException
	{
		if(instruction.startsWith("BIPUSH") || instruction.startsWith("SIPUSH")){
			tempInstructions.add("   "+"ldc.i4.s "+operand+"\n"); 
			instructionCount++;
		}	
		//?? else if(instruction.equalsIgnoreCase("SIPUSH"))  ???
		// Not sure what to use for SIPUSH
	
		/** New array  : One dimensional  **/
		/** Instruction: NEWARRAY	**/
		
		if(instruction.equalsIgnoreCase("NEWARRAY")) {
			
			tempInstructions.add("   "+"newarr "+ILUtility.findType(operand)+"\n"); 
			instructionCount++;
			multiArrayFlag = 0;
		}
	}
	
	
	public void toCorrespondingIL(String instruction) throws IOException
	{
		/* Conversion for iconst_m1 to iconst_5
		 * lconst_0 and lconst_1
		 * fconst_0 and fconst_1
		 * dconst_0 and dconst_1
		 *   
		 */
		
		
		// Length of these instructions are at least 8
		// for the __CONST__ instructions
		//System.out.println("INS::::"+instruction);
		
		if(instruction.length()>=8 && instruction.startsWith("CONST",1)) 
		{
			
			System.out.println("INS::::"+instruction);
			
			if(instruction.equalsIgnoreCase("ACONST_NULL")){
				tempInstructions.add("   "+"ldnull"+""+"\n");
				instructionCount++;
			}
			
			if(instruction.startsWith("I"))
			{
				System.out.println("---->"+instruction);
				if(instruction.endsWith("m1"))
					tempInstructions.add("    "+"ldc.i4.m1"+""+"\n");
				
				else if(instruction.endsWith("0"))
					tempInstructions.add("    "+"ldc.i4.0"+""+"\n");
				
				else if(instruction.endsWith("1"))
					tempInstructions.add("    "+"ldc.i4.1"+""+"\n");
				
				else if(instruction.endsWith("2"))
					tempInstructions.add("    "+"ldc.i4.2"+""+"\n");
				
				else if(instruction.endsWith("3"))
					tempInstructions.add("    "+"ldc.i4.3"+""+"\n");
				
				else if(instruction.endsWith("4"))
					tempInstructions.add("    "+"ldc.i4.4"+""+"\n");
				
				else if(instruction.endsWith("5"))
					tempInstructions.add("    "+"ldc.i4.5"+""+"\n");
				
				instructionCount++;
				
			}
			
			// For fconst_0 , fconst_1 and f_const_2
			
			if(instruction.startsWith("F"))
			{
				
				if(instruction.endsWith("0")){
					tempInstructions.add("    "+"ldc.i4.0"+""+"\n");
					tempInstructions.add("    "+"conv.r4"+""+"\n");
				}
				else if(instruction.endsWith("1")){
					tempInstructions.add("    "+"ldc.i4.1"+""+"\n");
					tempInstructions.add("    "+"conv.r4"+""+"\n");
				}
				else if(instruction.endsWith("2")){
					tempInstructions.add("    "+"ldc.i4.2"+""+"\n");
					tempInstructions.add("    "+"conv.r4"+""+"\n");
				}
				
				instructionCount++;
				instructionCount++;
			}
			
			// For lconst_0 and lconst_1
			
			if(instruction.startsWith("L"))
			{
				
				if(instruction.endsWith("0")){
					tempInstructions.add("    "+"ldc.i4.0"+""+"\n");
					tempInstructions.add("    "+"conv.i8"+""+"\n");
				}
				else if(instruction.endsWith("1")){
					tempInstructions.add("    "+"ldc.i4.1"+""+"\n");
					tempInstructions.add("    "+"conv.i8"+""+"\n");
				}
				
				instructionCount++;
				instructionCount++;
			}
			
			// For dconst_0 and dconst_1
			
			if(instruction.startsWith("D"))
			{
				
				if(instruction.endsWith("0")){
					tempInstructions.add("    "+"ldc.i4.0"+""+"\n");
					tempInstructions.add("    "+"conv.r8"+""+"\n");
				}
				else if(instruction.endsWith("1")){
					tempInstructions.add("    "+"ldc.i4.1"+"\n");
					tempInstructions.add("    "+"conv.r8"+"\n");
				}
				
				instructionCount++;
				instructionCount++;
			}
			
		}
		
		
		/*
		 * ADDITION INSTRUCTIONS
		 * */
		
		if(instruction.endsWith("ADD"))	{	
			
			tempInstructions.add("   "+"add"+"\n");
			instructionCount++;
			
		}
		
		/*
		 * SUBTRACTION INSTRUCTIONS
		 * */
		
		
		
		if(instruction.endsWith("SUB")){		
			
			tempInstructions.add("   "+"sub"+"\n");
			instructionCount++;
			
		}
		
		/*
		 * MULTIPLY INSTRUCTIONS
		 * */
		
		if(instruction.endsWith("MUL"))	{	
			
			tempInstructions.add("   "+"mul"+"\n");
		
			instructionCount++;
			
		}
		
		/*
		 * DIVISION INSTRUCTIONS
		 * */
		
		if(instruction.endsWith("DIV")){		
			
			tempInstructions.add("   "+"div"+"\n");
		
			instructionCount++;
			
		}
		
		/*
		 * Remainder INSTRUCTIONS
		 * */
		
		if(instruction.endsWith("REM")){		
			
			tempInstructions.add("   "+"rem"+"\n");
		
			instructionCount++;
			
		}
		
		/*
		 * NEGATION INSTRUCTIONS
		 * */
		
		if(instruction.endsWith("NEG")){		
			
			tempInstructions.add("   "+"neg"+"\n");
			instructionCount++;
			
		}
		
		
		/*
		 * SHIFT ISNTRUCTIONS
		 * 
		 */
		
		if(instruction.endsWith("SHL")){
			tempInstructions.add("   "+"shl"+"\n");
			instructionCount++;
			
		}
		
		else if(instruction.endsWith("SHR")){
			tempInstructions.add("   "+"shr"+"\n");
			instructionCount++;
			
		}
		
		else if (instruction.endsWith("USHR")){
			
			tempInstructions.add("   "+"shr.un"+"\n");
			instructionCount++;
			
		}
		/*
		 * LOGICAL INSTRUCTIONS
		 * 
		 * *
		 */
		
		if(instruction.endsWith("OR")){
			tempInstructions.add("   "+"or"+"\n");
			instructionCount++;
		}
		
		else if(instruction.endsWith("XOR")){
			tempInstructions.add("   "+"xor"+"\n");
			instructionCount++;
		}
		
		else if(instruction.endsWith("AND")){
			tempInstructions.add("   "+"and"+"\n");
			instructionCount++;
		}
		
		
		/*
		 * * Duplicate Instructions **/
		
		if(instruction.equalsIgnoreCase("dup")){
			tempInstructions.add("   "+"dup"+"\n");
			instructionCount++;
		}
		
		/*
		 * * Pop instructions **/
		
		if(instruction.startsWith("POP"))
		{
			
			if(instruction.equalsIgnoreCase("POP")){
					tempInstructions.add("   "+"dup"+"\n");
					instructionCount++;
					
			}
			else if(instruction.equalsIgnoreCase("POP2")){
					tempInstructions.add("   "+"pop"+"\n");
					tempInstructions.add("   "+"pop"+"\n");
					
					instructionCount++;
					instructionCount++;
					
			}		
		}
		
		
		
		
		/*
		 * 
		 * *   Type Conversion Instructions  
		 * */
	
		if(instruction.length()==3 && instruction.indexOf('2')==1)
		{
			
			
			// Integer to others
			if(instruction.equalsIgnoreCase("i2l"))
				tempInstructions.add("   "+"conv.i8"+"\n");
			else if(instruction.equalsIgnoreCase("i2f"))
				tempInstructions.add("   "+"conv.r4"+"\n");
			else if(instruction.equalsIgnoreCase("i2d"))
				tempInstructions.add("   "+"conv.r8"+"\n");
			
			
			// Long to others
			
			if(instruction.equalsIgnoreCase("l2i"))
				tempInstructions.add("   "+"conv.i4"+"\n");
			else if(instruction.equalsIgnoreCase("l2f"))
				tempInstructions.add("   "+"conv.r4"+"\n");
			else if(instruction.equalsIgnoreCase("l2d"))
				tempInstructions.add("   "+"conv.r8"+"\n");
			
			// Float to others
			
			if(instruction.equalsIgnoreCase("f2i"))
				tempInstructions.add("   "+"conv.i4"+"\n");
			else if(instruction.equalsIgnoreCase("f2l"))
				tempInstructions.add("   "+"conv.i8"+"\n");
			else if(instruction.equalsIgnoreCase("f2d"))
				tempInstructions.add("   "+"conv.r8"+"\n");
			
			
			
			// Double to others
			
			if(instruction.equalsIgnoreCase("d2i"))
				tempInstructions.add("   "+"conv.i4"+"\n");
			else if(instruction.equalsIgnoreCase("d2l"))
				tempInstructions.add("   "+"conv.i8"+"\n");
			else if(instruction.equalsIgnoreCase("d2f"))
				tempInstructions.add("   "+"conv.r4"+"\n");
			
			
			instructionCount++;
			
		
		}
			
			
			/**
			 * 
			 *   RETURN INSTRUCTIONS
			 */
			 
			
			if(instruction.endsWith("RETURN")){
				tempInstructions.add("   "+"ret"+"\n");
				instructionCount++;
				
			}
			
			/**
			 *    Array Length instruction
			 */
			
			
			if(instruction.equalsIgnoreCase("ARRAYLENGTH")){
				tempInstructions.add("   "+"ldlen"+"\n"); // not sure
				instructionCount++;
				
			}
			/*
			 * 
			 * * STORE INSTRUCTIONS  *
			 * */
		
			
			if(instruction.endsWith("STORE"))
			{
				
				if(instruction.equalsIgnoreCase("IASTORE"))
					tempInstructions.add("   "+"stelem.i4"+"\n"); 
				
				else if(instruction.equalsIgnoreCase("LASTORE"))
					tempInstructions.add("   "+"stelem.i8"+"\n"); 
				
				else if(instruction.equalsIgnoreCase("DASTORE"))
					tempInstructions.add("   "+"stelem.r8"+"\n"); 
				
				else if(instruction.equalsIgnoreCase("AASTORE"))
					tempInstructions.add("   "+"stelem.ref"+"\n"); 
					
				else if(instruction.equalsIgnoreCase("BASTORE"))
					tempInstructions.add("   "+"stelem.i1"+"\n"); 
				
				else if(instruction.equalsIgnoreCase("CASTORE"))
					tempInstructions.add("   "+"stelem.i"+"\n"); // NOT SURE 
				
				
				else if(instruction.equalsIgnoreCase("FASTORE"))
					tempInstructions.add("   "+"stelem.r4"+"\n"); 
				
				else if(instruction.equalsIgnoreCase("SASTORE"))
					tempInstructions.add("   "+"stelem.i2"+"\n");
				
				instructionCount++;
				
				
			}
				
		
			
			/*
			 * 
			 * * LOAD INSTRUCTIONS  *
			 * */
		
			
			if(instruction.endsWith("LOAD"))
			{
				
				if(multiArrayFlag == 0){
						if(instruction.equalsIgnoreCase("IALOAD"))
							tempInstructions.add("   "+"ldelem.i4"+"\n"); 
						
						else if(instruction.equalsIgnoreCase("LALOAD"))
							tempInstructions.add("   "+"ldelem.i8"+"\n"); 
						
						else if(instruction.equalsIgnoreCase("DALOAD"))
							tempInstructions.add("   "+"ldelem.r8"+"\n"); 
						
						else if(instruction.equalsIgnoreCase("AALOAD"))
						{
							
							
								tempInstructions.add("   "+"ldelem.ref"+"\n"); 
							
							
							
						}	
						
						else if(instruction.equalsIgnoreCase("BALOAD"))
							tempInstructions.add("   "+"ldelem.i1"+"\n"); // not sure for boolean 
						
						//else if(instruction.equalsIgnoreCase("CALOAD")) ????
							//methInstructions.add("   "+"ldelem.i"+"\n"); // NOT SURE 
						
						
						else if(instruction.equalsIgnoreCase("FALOAD"))
							tempInstructions.add("   "+"ldelem.r4"+"\n"); 
						
						else if(instruction.equalsIgnoreCase("SALOAD"))
							tempInstructions.add("   "+"ldelem.i1"+"\n"); 
				
						instructionCount++;
				}
				
				else if(multiArrayFlag == 1 && instruction.equalsIgnoreCase("AALOAD") ){
					tempInstructions.add(" "+multiArraySignature);
				
					instructionCount++;
				}
			}
				
		
	
			/*
			 * *
			 * ILOAD,LLOAD,DLOAD,FLOAD,ALOAD
			 * 
			 */
			
			/*if(instruction.equalsIgnoreCase("ILOAD_0")||instruction.equalsIgnoreCase("LLOAD_0")||instruction.equalsIgnoreCase("DLOAD_0")||instruction.equalsIgnoreCase("FLOAD_0")||instruction.equalsIgnoreCase("ALOAD_0")){
				tempInstructions.add("   "+"ldloc.0"+"\n");
				instructionCount++;
				
			}
			else if(instruction.equalsIgnoreCase("ILOAD_1")||instruction.equalsIgnoreCase("LLOAD_1")||instruction.equalsIgnoreCase("DLOAD_1")||instruction.equalsIgnoreCase("FLOAD_1")||instruction.equalsIgnoreCase("ALOAD_1")){
				 	
					if(meth.isStatic == false)
						tempInstructions.add("   "+"ldloc.1"+"\n");
					else
						tempInstructions.add("   "+"ldloc.0"+"\n");
					
				 	instructionCount++;
			}

			else if(instruction.equalsIgnoreCase("ILOAD_2")||instruction.equalsIgnoreCase("LLOAD_2")||instruction.equalsIgnoreCase("DLOAD_2")||instruction.equalsIgnoreCase("FLOAD_2")||instruction.equalsIgnoreCase("ALOAD_2")){
					
				if(meth.isStatic == false)
					tempInstructions.add("   "+"ldloc.2"+"\n");
				else
					tempInstructions.add("   "+"ldloc.1"+"\n");
				
				instructionCount++;
			}
			
			else if(instruction.equalsIgnoreCase("ILOAD_3")||instruction.equalsIgnoreCase("LLOAD_3")||instruction.equalsIgnoreCase("DLOAD_3")||instruction.equalsIgnoreCase("FLOAD_3")||instruction.equalsIgnoreCase("ALOAD_3")){
					
				if(meth.isStatic == false)
					tempInstructions.add("   "+"ldloc.3"+"\n");
				else
					tempInstructions.add("   "+"ldloc.2"+"\n");
				
				instructionCount++;
			}
				*/

			/*
			 * *
			 * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
			 * 
			 */
			/*
			
			if(instruction.equalsIgnoreCase("ISTORE_0")||instruction.equalsIgnoreCase("LSTORE_0")||instruction.equalsIgnoreCase("DSTORE_0")||instruction.equalsIgnoreCase("FSTORE_0")||instruction.equalsIgnoreCase("ASTORE_0")){
					tempInstructions.add("   "+"stloc.0"+"\n");
					instructionCount++;
			}	
			
			else if(instruction.equalsIgnoreCase("ISTORE_1")||instruction.equalsIgnoreCase("LSTORE_1")||instruction.equalsIgnoreCase("DSTORE_1")||instruction.equalsIgnoreCase("FSTORE_1")||instruction.equalsIgnoreCase("ASTORE_1")){
					
				if(meth.isStatic == false)
					tempInstructions.add("   "+"stloc.1"+"\n");
				else
					tempInstructions.add("   "+"stloc.0"+"\n");
				
				instructionCount++;
			}

			else if(instruction.equalsIgnoreCase("ISTORE_2")||instruction.equalsIgnoreCase("LSTORE_2")||instruction.equalsIgnoreCase("DSTORE_2")||instruction.equalsIgnoreCase("FSTORE_2")||instruction.equalsIgnoreCase("ASTORE_2")){
				
				if(meth.isStatic == false)
					tempInstructions.add("   "+"stloc.2"+"\n");
				else
					tempInstructions.add("   "+"stloc.1"+"\n");
				
				instructionCount++;
			}
			
			else if(instruction.equalsIgnoreCase("ISTORE_3")||instruction.equalsIgnoreCase("LSTORE_3")||instruction.equalsIgnoreCase("DSTORE_3")||instruction.equalsIgnoreCase("FSTORE_3")||instruction.equalsIgnoreCase("ASTORE_3")){
				if(meth.isStatic == false)	
					tempInstructions.add("   "+"stloc.3"+"\n");
				else
					tempInstructions.add("   "+"stloc.2"+"\n");
				
				instructionCount++;
			}
					
			*/
			
			

			/*
			 * *
			 * lcmp,fcmpl,fcmpg,dcmpl,dcmpg
			 * 
			 */
			
			
			//methInstructions.add("   "+"cgt"+"\n");
			//methInstructions.add("   "+"pop"+"\n");
			//methInstructions.add("   "+"add"+"\n");
	
	}
	
	// Have to omit instruction
	public void toCorrespondingJumpIL(int opcode, String instruction, String label)
	{
		
		  switch(opcode) {
		  	
		  	
		  	case IF_ICMPEQ:	// http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html#if_icmpcond
		  	case IF_ICMPNE:
		  	case IF_ICMPLT:
		  	case IF_ICMPGE:
		  	case IF_ICMPGT:
		  	case IF_ICMPLE:
		  	case IF_ACMPEQ:	
		  	case IF_ACMPNE:
		  		this.genJumpInstructions(instruction,label);
		  		break;
		  		
		  	case IFEQ:	// http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html#ifcond
		  	case IFNE:
		  	case IFLT:
		  	case IFGE:
		  	case IFGT:
		  	case IFLE:
		      
		  		this.genJumpInstructions(instruction,label);
		      
		      break;
		      
		  	case GOTO:
		  	case JSR:
		  		this.genJumpInstructions(instruction,label);
		  		break;
		  }
		  
		  	/*
		     
		  	case GOTO:	// http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc5.html#goto
		  	case JSR:
		      mv.visitMethodInsn(INVOKESTATIC, VM_FQ, BYTECODE_NAME[opcode], V_V);
		      break;
		      
		  	case 200:	// http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc5.html#goto_w
		  	case 201:
		  		mv.visitMethodInsn(INVOKESTATIC, VM_FQ, BYTECODE_NAME[opcode], V_V);
		  		break;
		  		
		  	default:
		  		check(false, BYTECODE_NAME[opcode]+" is not a jump instruction.");

		 * 
		 * 
		 */

	}
	
	// Visit Jump Instructions
	
	public void genJumpInstructions(String instruction,String label)
	{
		
		int offset;
		
		
		
		String iLVersion="";
		
		if(instruction.equalsIgnoreCase("IF_ICMPEQ")||instruction.equalsIgnoreCase("IFEQ"))
			iLVersion = "beq";
		else if(instruction.equalsIgnoreCase("IF_ICMPNE")||instruction.equalsIgnoreCase("IFNE"))
			iLVersion = "bne.un";
		else if(instruction.equalsIgnoreCase("IF_ICMPLT")||instruction.equalsIgnoreCase("IFLT"))
			iLVersion = "blt";
		else if(instruction.equalsIgnoreCase("IF_ICMPGE")||instruction.equalsIgnoreCase("IFGE"))
			iLVersion = "bge";
		else if(instruction.equalsIgnoreCase("IF_ICMPGT")||instruction.equalsIgnoreCase("IFGT"))
			iLVersion = "bgt";
		else if(instruction.equalsIgnoreCase("IF_ICMPLE")||instruction.equalsIgnoreCase("IFLE"))
			iLVersion = "ble";
		else if(instruction.equalsIgnoreCase("IF_ACMPEQ"))
			iLVersion = "beq";
		else if(instruction.equalsIgnoreCase("IF_ACMPNE"))
			iLVersion = "bne.un";
		
		else if(instruction.equalsIgnoreCase("IFNULL"))
			iLVersion = "brnull";
		
		else if(instruction.equalsIgnoreCase("IFNONNULL"))
			iLVersion = "brinst";
		
		else if(instruction.equalsIgnoreCase("JSR") || instruction.equalsIgnoreCase("GOTO"))
			iLVersion = "br";
		
			
		if(instruction.startsWith("IF_ICMP") || instruction.startsWith("IF_ACMP"))
		{
			offset = ILUtility.getLabelOffset(label, ls); 
			if(offset==0)
				tempInstructions.add("Unknown"+" "+label+" "+iLVersion+" "+instructionCount+" End");
			else
				tempInstructions.add(iLVersion+" IL_"+offset+"\n");
			
			instructionCount++;
		}
		
		// 
		else if(instruction.length()== 4 && instruction.startsWith("IF"))
		{
			offset = ILUtility.getLabelOffset(label, ls);  
			if(offset==0)
				tempInstructions.add("Unknown"+" "+label+" "+iLVersion+" "+instructionCount+" End");
			else
				tempInstructions.add(iLVersion+" IL_"+offset+"\n");
			
			instructionCount++;
		}
		
		else if(instruction.equalsIgnoreCase("JSR") || instruction.equalsIgnoreCase("GOTO") )
		{
			offset = ILUtility.getLabelOffset(label, ls); 
			if(offset==0)
				tempInstructions.add("Unknown"+" "+label+" "+iLVersion+" "+instructionCount+" End");
			else
				tempInstructions.add(iLVersion+" IL_"+offset+"\n");
			
			instructionCount++;
		}
	}
	
	
	// Convert the Type Instructions
	
	public void doTypeInsConvertion(int opcode,String type)
	{
		if(opcode == NEW)
			pendingTypeLists.add(type);
		// No operation
	}

	
	// Visit Increment instruction
	
	public void toIncInstruction(int i,int value)
	{
		
		int argCount = meth.GetParametersCount();
		int target;
		
		if(meth.isStatic)
			argCount--;
		
		if(i<=argCount)
			target = i;
		else
			target = (i-argCount-1);
		
		
		
		if(target<=3)
			tempInstructions.add("   "+"ldloc."+target+"\n");
		else
			tempInstructions.add("   "+"ldloc "+target+"\n");
		
		tempInstructions.add("   "+"ldc.i4 "+value+"\n");
		tempInstructions.add("   "+"add"+"\n");
		
		if(target<=3)
			tempInstructions.add("   "+"stloc."+target+"\n");
		else
			tempInstructions.add("   "+"stloc "+target+"\n");
		
		instructionCount+=4;
	}
	
	
	/************************************************/
	/**** CONVERT A MULTIDIMENTIONAL ARRAY		****/
	/***********************************************/
	
	
	public void convertArrayInsn(String arrayTypeDesc, int nrDimensions)
	{
		int i;
		System.out.println("BOOOOOOOOOOOOOOOOOOOOOOOOOO");
		
		StringBuffer array_ins = new StringBuffer();
		StringBuffer multArray = new StringBuffer();
		
		String type = ILUtility.resolveShortType(arrayTypeDesc);
		//iLInstructions.add("   "+"newarr "+ILUtility.findType(operand)+"\n"); 
		//instructionCount++;
		
		array_ins.append("newobj  instance void	");
		multArray.append("call instance "+type+" "+type+" [");
		
		multiArrayFlag = 1;
		array_ins.append(type+"[");
		
		for(i=0;i<nrDimensions;i++) {
			array_ins.append("0...");
			multArray.append("0...");
			
			if(i<(nrDimensions-1)){
				array_ins.append(",");
				multArray.append(",");
			}
		}
		
		array_ins.append("]::.ctor(");
		multArray.append("]::Get(");
		
		for(i=0;i<nrDimensions;i++) {
			array_ins.append("int32");
			multArray.append("int32");
			
			if(i<(nrDimensions-1)){
				array_ins.append(",");
				multArray.append(",");
			}	
		}
		
		array_ins.append(")\n");
		multArray.append(")@\n");
		
		
		multiArraySignature = new String(multArray.toString());
		
		tempInstructions.add("   "+array_ins.toString());
		instructionCount++;
	}
	
	
	public void setStackAndLocalVariableDirective(int size,String localVariables,int totalVarCount,int argumentCount)
	{
		StringBuffer sb = new StringBuffer();
		sb.append("	.locals init(");
		sb.append(localVariables);
		sb.append(")\n");
		
		tempInstructions.add(sb.toString());
		tempInstructions.add("	.maxstack "+size+"\n");
	}
	


	// Resolve Branch Targets and final tasks
	
	public void endMethodVisit()
	{
		instructionCount = 0;
		tempInstructions.add("\n\n");
		tempInstructions.add("}\n\n");

		int count = 0;
		int multArrayPrint=0;
		StringBuffer test = new StringBuffer();
		
		// Now iterate the instruction list
		Iterator<String> it = tempInstructions.iterator();

        while(it.hasNext()) {
        	String value=(String)it.next();
	          
        	if(value.startsWith("Unknown")) {
        		value = ILUtility.resolveBranchTarget(value, ls);
	        }
	          
	        if(!value.equalsIgnoreCase("")) {
	        	  
	        	if(multArrayPrint==0) {
	        		if(value.endsWith("@\n")) {
	        			
	        			multArrayPrint = 1;
	        			test.append(value);
									
	        			// Discarding the character "@"
	        			test.deleteCharAt(test.length()-2);
	        		}
	        		else {
	        			methInstructions.add(value);
			        }
				}// End of if multiArray was not present
			        	
	        	else if(multArrayPrint == 1) {
	        		
	        		if(value.contains("ldc.i4")) {
	        			methInstructions.add(value);
	        		}
					else {
						multArrayPrint = 0;
						methInstructions.add(test.toString());
						methInstructions.add(value);
						// Making the buffer empty again
						test.delete(0, test.length()-1);
					}	
	        	} // End of If (multiArray Present)
	        }// (end of if value!="")    	
          count++;
        } // End of while
        
	}
	
	
	// Supports only System.out.println
	// operand either string or integer
	public void doMethodCall(int opcode, String owner, String name, String desc, String currentClassName)
	{
		StringBuffer constructorSign = new StringBuffer();
		StringBuffer methodCall = new StringBuffer();
		
		Type[] argTypes = Type.getArgumentTypes(desc);
		Type returnType = Type.getReturnType(desc);
		
		String ilParams = ILUtility.getFormattedIlParams(argTypes);
		
		if(opcode == INVOKEVIRTUAL) {
			
	  		if(name.equals("println")) {
		  		if(desc.contains("Ljava/lang/String;"))
		  			tempInstructions.add("   "+"call void [mscorlib]System.Console::WriteLine(string)\n");
		  		else if(desc.contains("I)"))
		  			tempInstructions.add("   "+"call void [mscorlib]System.Console::WriteLine(int32)\n");
		  	}
	  		
	  		else {
	  			if (owner.equals(currentClassName)) {
	  				methodCall.append("call instance");
	  			}
	  			else {
	  				methodCall.append("callvirt instance");
	  			}
	  		}
	  	}

		else if(opcode == INVOKESTATIC) {
			methodCall.append("call");
		}

		else if(opcode == INVOKESPECIAL) {
			// does support only within same package
			if(!owner.contains(".")) {
				
				if( pendingTypeLists==null){
					constructorSign.append("call instance");
				
				}
				else 
				{
					int size = pendingTypeLists.size();
					if(size==0)
						constructorSign.append("call instance");
					
					else{
						String type = pendingTypeLists.get(size-1);
						if(type.equals(owner))
						{
							constructorSign.append("newobj instance");
							pendingTypeLists.remove(size-1);
						}
					}
				}
				
				if(owner.equals("java/lang/Object"))
					owner ="[mscorlib]System.Object";
				
				if(returnType.toString().equals("V"))
					constructorSign.append(" void "+owner+"::.ctor");
				else
					constructorSign.append(" void "+owner+"::.ctor");
				
				constructorSign.append(ilParams);
				constructorSign.append("\n");
				
				// System.out.println(constructorSign);
				tempInstructions.add(constructorSign.toString());
			}
		}
		
		if(methodCall.toString().startsWith("call")) {
			methodCall.append(" " + ILUtility.resolveShortType(returnType.toString()) + " " + owner + "::" + name + ilParams);
			tempInstructions.add(methodCall.toString());
			tempInstructions.add("\n");
		}
	}
	
	
	
	public void maintainLabels(String label)
	{
		if(!ls.contains(label)) {
			ls.add(label);
			tempInstructions.add("IL_"+ls.size()+":\n");
		}
	}

}
